package com.ruoyi.web.controller.accommon;

import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.system.mapper.SysRoleMapper;
import com.ruoyi.web.bean.ProcessCommonReq;
import com.ruoyi.web.domain.ProcessCommon;
import com.ruoyi.web.mapper.ProcessCommonMapper;
import com.ruoyi.web.util.AjaxResponse;
import com.ruoyi.web.util.GlobalConfig;
import org.activiti.api.process.model.ProcessInstance;
import org.activiti.api.process.model.builders.ProcessPayloadBuilder;
import org.activiti.api.process.runtime.ProcessRuntime;
import org.activiti.api.task.model.Task;
import org.activiti.api.task.model.builders.TaskPayloadBuilder;
import org.activiti.api.task.runtime.TaskRuntime;
import org.activiti.bpmn.model.*;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.Execution;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;

/**
 * @author wfl
 * @date 2021年04月07日 10:25
 */
@RestController
@RequestMapping("processCommon")
public class ProcessCommonController {

    @Autowired
    private ProcessRuntime processRuntime;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private ProcessCommonMapper processCommonMapper;

    @Autowired
    protected TaskService taskService;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private SysRoleMapper sysRoleMapper;

    @Autowired
    private TaskRuntime taskRuntime;

    @Autowired
    private HistoryService historyService;


    //启动流程

    @PostMapping("startProcessCommon")
    public AjaxResponse startProcessCommon(@AuthenticationPrincipal LoginUser user, @RequestBody ProcessCommonReq req) {
        try {
            //处理候选人
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionId(req.getProcessDefinId()).singleResult();
            Map<String, String> userElMap = nextTaskDefinition(processDefinition.getId());

            //新增记录
            Long userId = user.getUser().getUserId();
            String userName = user.getUser().getUserName();
            ProcessCommon processCommon = new ProcessCommon();
            processCommon.setProcessDefinitionKey(req.getProcessKey());
            processCommon.setProcessInstanceJson(req.getFormJson());
            processCommon.setCreateUser(String.valueOf(userId));
            processCommonMapper.insert(processCommon);
            HashMap<String, Object> paramMap = req.getParamMap();
            paramMap.put("user", userName);

            //设置所有节点的候选人el表达式  变为真正的候选人
            if (userElMap != null && userElMap.size() > 0) {
                Set<String> keys = userElMap.keySet();
                for (String key : keys) {
                    String value = userElMap.get(key);
                    paramMap.put(key, value);
                }
            }

            //启动流程
            ProcessInstance processInstance = processRuntime.start(ProcessPayloadBuilder
                    .start()
                    .withBusinessKey(String.valueOf(processCommon.getProcessCommonId()))
                    .withProcessDefinitionKey(req.getProcessKey())
                    .withVariables(paramMap)
                    .build());
            processCommon.setProcessInstanceId(processInstance.getId());


            //更新记录
            processCommonMapper.updateByPrimaryKey(processCommon);


            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), "启动成功,processInstanceId=" + processInstance.getId());
        } catch (Exception e) {
            System.out.println(e);
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "启动失败", e.toString());
        }
    }

    public static void main(String[] args) {
        String usersEl = "${hxr}";
        usersEl = usersEl.substring(usersEl.indexOf("${") + 2);
        usersEl = usersEl.substring(0, usersEl.indexOf("}"));
        System.out.println(usersEl);

    }

    //获取每个节点 候选人的真正的id
    public Map<String, String> nextTaskDefinition(String procDefinId) {
        BpmnModel model = repositoryService.getBpmnModel(procDefinId);
        List<String> usersEls = new ArrayList<>();
        if (model != null) {
            Collection<FlowElement> flowElements = model.getMainProcess().getFlowElements();
            for (FlowElement e : flowElements) {
                System.out.println("flowelement id:" + e.getId() + "  name:" + e.getName() + "   class:" + e.getClass().toString());
                //判断是否是 用户节点
                if (e instanceof UserTask) {
                    UserTask userTask = (UserTask) e;
                    List<String> candidateUsers = ((UserTask) e).getCandidateUsers();
                    if (candidateUsers != null && candidateUsers.size() > 0) {
                        String usersEl = candidateUsers.get(0);
                        usersEls.add(usersEl);
                    }
                }
            }
        }
        Map resultMap = new HashMap();
        if (usersEls != null && usersEls.size() > 0) {
            for (String usersEl : usersEls) {
                usersEl = usersEl.substring(usersEl.indexOf("${") + 2);
                usersEl = usersEl.substring(0, usersEl.indexOf("}"));
                List<SysUser> usersByRoleNames = sysRoleMapper.getUsersByRoleName(usersEl);
                if (usersByRoleNames != null && usersByRoleNames.size() > 0) {
                    String userIds = "";
                    for (int i = 0; i < usersByRoleNames.size(); i++) {
                        SysUser sysUser = usersByRoleNames.get(i);
                        if (i < (usersByRoleNames.size() - 1)) {
                            userIds = userIds + sysUser.getUserName() + ",";
                        } else {
                            userIds = userIds + sysUser.getUserName();
                        }
                    }
                    resultMap.put(usersEl, userIds);
                }
            }
        }
        return resultMap;
    }


    //审核通过
    @PostMapping("compleTaskCommonProcess")
    public AjaxResponse compleTaskCommonProcess(@AuthenticationPrincipal LoginUser user, @RequestBody ProcessCommonReq req) {
        String taskId = req.getTaskId();
        try {

            Task task = taskRuntime.task(taskId);

            if (task.getAssignee() == null) {
                taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(task.getId()).build());
            }
            taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId(task.getId())
                    //.withVariable("isAgree", isAgree)//执行环节设置变量
                    .build());


            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), null);
        } catch (Exception e) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "完成失败", e.toString());
        }


    }

    //驳回流程
    @PostMapping("backTaskCommonProcess")
    public AjaxResponse backTaskCommonProcess(@AuthenticationPrincipal LoginUser user, @RequestBody ProcessCommonReq req) {
        try {
            String taskId = req.getTaskId();
            Task task = taskRuntime.task(taskId);
            if (task.getAssignee() == null) {
                taskRuntime.claim(TaskPayloadBuilder.claim().withTaskId(task.getId()).build());
            }
            backProcess(task);
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.SUCCESS.getCode(),
                    GlobalConfig.ResponseCode.SUCCESS.getDesc(), null);
        } catch (Exception e) {
            return AjaxResponse.AjaxData(GlobalConfig.ResponseCode.ERROR.getCode(),
                    "完成失败", e.toString());
        }

    }


    /**
     * 退回到上一节点
     *
     * @param task 当前任务
     */
    public void backProcess(Task task) throws Exception {
        String processInstanceId = task.getProcessInstanceId();
        // 取得所有历史任务按时间降序排序
        List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(processInstanceId)
                .orderByTaskCreateTime()
                .desc()
                .list();
        if (htiList == null || htiList.size() < 2) {
            return;
        }
        // list里的第二条代表上一个任务
        HistoricTaskInstance lastTask = htiList.get(1);
        // list里第二条代表当前任务
        HistoricTaskInstance curTask = htiList.get(0);
        // 当前节点的executionId
        String curExecutionId = curTask.getExecutionId();
        // 上个节点的taskId
        String lastTaskId = lastTask.getId();
        // 上个节点的executionId
        String lastExecutionId = lastTask.getExecutionId();
        if (null == lastTaskId) {
            throw new Exception("LAST TASK IS NULL");
        }
        String processDefinitionId = lastTask.getProcessDefinitionId();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        String lastActivityId = null;
        List<HistoricActivityInstance> haiFinishedList = historyService.createHistoricActivityInstanceQuery()
                .executionId(lastExecutionId).finished().list();
        for (HistoricActivityInstance hai : haiFinishedList) {
            if (lastTaskId.equals(hai.getTaskId())) {
                // 得到ActivityId，只有HistoricActivityInstance对象里才有此方法
                lastActivityId = hai.getActivityId();
                break;
            }
        }
        // 得到上个节点的信息
        FlowNode lastFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(lastActivityId);
        // 取得当前节点的信息
        Execution execution = runtimeService.createExecutionQuery().executionId(curExecutionId).singleResult();
        String curActivityId = execution.getActivityId();
        FlowNode curFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(curActivityId);
        //记录当前节点的原活动方向
        List<SequenceFlow> oriSequenceFlows = new ArrayList<>();
        oriSequenceFlows.addAll(curFlowNode.getOutgoingFlows());
        //清理活动方向
        curFlowNode.getOutgoingFlows().clear();
        //建立新方向
        List<SequenceFlow> newSequenceFlowList = new ArrayList<>();
        SequenceFlow newSequenceFlow = new SequenceFlow();
        newSequenceFlow.setId("newSequenceFlowId");
        newSequenceFlow.setSourceFlowElement(curFlowNode);
        newSequenceFlow.setTargetFlowElement(lastFlowNode);
        newSequenceFlowList.add(newSequenceFlow);
        curFlowNode.setOutgoingFlows(newSequenceFlowList);
        // 完成任务
        taskService.complete(task.getId());
        //恢复原方向
        curFlowNode.setOutgoingFlows(oriSequenceFlows);
        org.activiti.engine.task.Task nextTask = taskService
                .createTaskQuery().processInstanceId(processInstanceId).singleResult();
        // 设置执行人
        if (nextTask != null) {
            taskService.setAssignee(nextTask.getId(), lastTask.getAssignee());
        }
    }


}
